package guru.util;

import java.util.Enumeration;
import java.util.Hashtable;


public abstract class ObjectPool{
	private long expirationTime;   
	protected Hashtable locked, unlocked;        
	protected int maxObjects;

	public ObjectPool(){
		expirationTime = 30000; // 30 seconds
		locked = new Hashtable();         
		unlocked = new Hashtable();
		maxObjects=10;
	}

	public abstract void expire(Object o);
	public abstract Object create();
	public abstract boolean isValid(Object o);

	synchronized public void checkIn( Object o ){
		locked.remove( o );
		unlocked.put( o, new Long( System.currentTimeMillis() ) );
		notifyAll();
	}

	synchronized public Object checkOut(){
	   long now = System.currentTimeMillis();
	   Object o;

		while(locked.size()>=maxObjects){
			try{
				wait();
			}
			catch(Exception e){}		
		}
        
		if( unlocked.size() > 0 )   {
	      Enumeration e = unlocked.keys();  
	      while( e.hasMoreElements() )      {
	         o = e.nextElement();           
	         if( ( now - ( ( Long ) unlocked.get( o ) ).longValue() ) > expirationTime )         {
	            // object has expired
	            unlocked.remove( o );
	            expire( o );
	            o = null;
	         }
	         else{
	            if( isValid( o ) )            {
	               unlocked.remove( o );
	               locked.put( o, new Long( now ) );                
	               return( o );
	            }
	            else{
	               // object failed validation
	               unlocked.remove( o );
	               expire( o );
	               o = null;
	            }
	         }
	      }
		}        
		// no objects available, create a new one
		o = create();        
		locked.put( o, new Long( now ) ); 
		return( o );
	}

}

